namespace Sirius.Collections
{
    using System.Collections;
    using System.Collections.Generic;
    using System.Linq;

    public class Lookup<TKey, TValue> : ILookup<TKey, TValue>
    {
        private readonly IDictionary<TKey, IEnumerable<TValue>> innerCollection = new Dictionary<TKey, IEnumerable<TValue>>();

        public IEnumerator<IEnumerable<TValue>> GetEnumerator()
        {
            return innerCollection.Values.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        public bool Contains(TKey key)
        {
            return innerCollection.ContainsKey(key);
        }

        public int Count
        {
            get { return innerCollection.Count; }
        }

        public IEnumerable<TValue> this[TKey key]
        {
            get { return innerCollection[key]; }
        }

        public void Add(TKey key, TValue value)
        {
            if (!innerCollection.ContainsKey(key))
            {
                innerCollection.Add(key, new List<TValue>());
            }

            ((List<TValue>)innerCollection[key]).Add(value);
        }

        public bool Equals(ILookup<TKey, TValue> other)
        {
            if (other.Count != Count)
                return false;

            var thisEnumerator = GetEnumerator();
            var otherEnumerator = other.GetEnumerator();

            while (thisEnumerator.MoveNext() && otherEnumerator.MoveNext())
            {
                var thisCollection = thisEnumerator.Current;
                var otherCollection = otherEnumerator.Current;

                if (thisCollection.Count() != otherCollection.Count())
                {
                    return false;
                }

                for (var i = 0; i < thisCollection.Count(); i++)
                {
                    var thisItem = thisCollection.ElementAt(i);
                    var otherItem = otherCollection.ElementAt(i);

                    if (!Equals(thisItem, otherItem))
                    {
                        return false;
                    }
                }
            }

            return true;
        }

        public override bool Equals(object obj)
        {
            if (obj is ILookup<TKey, TValue>)
            {
                return Equals(obj as ILookup<TKey, TValue>);
            }
            return false;
        }

        public override int GetHashCode()
        {
            return ( innerCollection != null ? innerCollection.GetHashCode() : 0 );
        }
    }
}